Crash Course of Scheme-lang Grammar
The let family in Scheme programming language. They are used to bind values to variables.
Table of Contents
1. Basic Grammars
1.1. Control Flow: cond, case, and/or/not
cond accepts a list of ((<predicate>) <value>). It examines each branch with the predicate, and immediately returns on match.
(define (classify x)
(cond ((> x 0) "Positive")
((< x 0) "Negative")
(else "Zero")))
; the ~else~ is equivalent to ~default~ in ~switch-case~ in other languages
(classify -5) ; => "Negative"
case pattern-matches on a variable against lists of candidates.
(case (* 2 3)
((1 3 5 7 9) 'odd)
((2 4 6 8) 'even)
(else 'unknown)) ; => 'even
and, or are short-circuit that they exit and returns the first satisfying element. In Scheme, only #f is false, all the rest (including 0 and '()) are true.
(and 1 2 3) ; => 3, returns the last value if all true
(and 1 #f 3) ; => #f
(or #f #f 5) ; => 5
(or #f #f) ; => #f
2. Advanced Grammars
2.1. let Family
2.2. Closures
2.3. Imperative Loops
In Scheme, we can use do keyword to write imperative style loops:
(do ((i 0 (+ i 1)) ; initialize variables
(s 0 (+ s i))) ; ((<var_1> <value_1> <update_1>))
((= i 5) s) ; ((<ending_condition>) <return_value>)
(display i)) ; body of loop
2.4. Quote, Quasiquote, Unquote
Quoting, an expression following ', stops the expression from being evaluated. It’s usually used to express symbols or literal values of lists.
Quasiquote, an expression following `, is similar to quoting, but it allows to evaluate expressions following an “unquote” (i.e., a comma ,). Unquote-slicing ,@ flattens a list and concatenate it into the outter list. But it only consumes one layer of “list wrapper”
(define lst '(3 4 5))
`(1 2 ,lst) ; => (1 2 (3 4 5))
`(1 2 ,@lst) ; => (1 2 3 4 5)
(define lst '((3 4 5)))
`(1 2 ,lst) ; => (1 2 ((3 4 5)))
`(1 2 ,@lst) ; => (1 2 (3 4 5))
2.5. Hygienic Macro
The behaviour is similar to macros in C, but Scheme will automatically try to avoid name conflicts between external variables and in-macro variables.